/*********************************************************
*               点阵贪吃蛇
*
**********************************************************/
#include <reg52.h>
#include <math.h>
#include "code.h"
#define uchar unsigned char
#define MAX_length 20       //最大长度
#define SPEED 8
#define INIT_length 3
#define hang_l P0             //高电平有效
#define hang_h P2             //高电平有效
#define lie  P1
sbit beepIO=P3^2;
sbit up=P3^6;             
sbit down=P3^4;
sbit right=P3^5;
sbit left=P3^7;
char x[MAX_length+1];    
char y[MAX_length+1];          
uchar current_length,i,j,jj,current_speed,key_flag=0;  //当前蛇长，通用循环变量，当前速度		
char addx,addy;   //位移偏移量
uchar music_m,music_n;  
void delay(int ms);
uchar knock();
void key_scan();
uchar transform(uchar temp) ;
void display(uchar speed);
void cartoon_1();
void cartoon_2();
void music_delay(uchar p);
void music_pause();
void display_music();
void di();
/*****************
主程序
*****************/	
void main(void)
{
	cartoon_1();
	current_speed=SPEED;
  lie=0xff;
  hang_l=0x00;
  hang_h=0x00;
  //display_music();
	
	
	while(1) //只要进了就不出的最大循环     
 {
  for(i=4;i<MAX_length+1;i++) x[i]=100;
	for(i=4;i<MAX_length+1;i++) y[i]=100;         //初始化
  x[0]=6;y[0]=6;                                //果子                            
  current_length=INIT_length;                            //蛇长 current_length=-1
  x[1]=2;y[1]=0;                                //蛇头
  x[2]=1;y[2]=0;                                //蛇尾1
	x[3]=0;y[3]=0;
  addx=0;addy=0;                                //位移偏移
	 
  while(1) //等待状态循环
 { if(~(left&right&up&down))
	 {
		 delay(10);
     if(~(left&right&up&down)){  break;  }
	 }
     display(1);
 }  //从这开始进入游戏
	
  while(1)  //游戏内循环       
  {
		display(current_speed);
    if(knock())             //判断碰撞   进入则跳出游戏循环
    {  
     cartoon_2();display_music();			
		 current_speed=SPEED;break;
		}                          
    if((x[0]==x[1]+addx)&(y[0]==y[1]+addy))         //是否吃东西
     {
			  di();
			  current_length++;
		   if(current_length==MAX_length+1)
		    {
				current_length=INIT_length;   current_speed=current_speed-4;
		    for(i=INIT_length;i<MAX_length+1;i++)  x[i]=100;
        for(i=INIT_length;i<MAX_length+1;i++)  y[i]=100;
		    }
        for(i=0;i<=(rand()%8+x[1]+y[1]);i++)
				{x[0]=rand()%15;y[0]=rand()%15;  }   //产生随机分布的果子
      }
      for(i=current_length;i>1;i--)
      {   x[i]=x[i-1];y[i]=y[i-1];    }          
      x[1]=x[1]+addx;
			y[1]=y[1]+addy;                     //移动
  }						
 }			
}                  //*******  main bottom  *********

/********************
延时程序
*********************/
void delay(int ms)//比较精确的一毫秒延时
{
   int x,y;
   for(x=ms;x>0;x--)
      for(y=123;y>0;y--);                    
}
void music_delay(uchar p)
{
    uchar i,j; 
    for(;p>0;p--)
    for(i=181;i>0;i--)
    for(j=181;j>0;j--);
}
void music_pause()
{
    uchar i,j;
    for(i=150;i>0;i--)
    for(j=150;j>0;j--);
}
/*******************************************
判断碰撞
*******************************************/
uchar knock()
{  
	uchar k=0;
  if(x[1]>15||y[1]>15)  k=1; 
  if(x[1]<0||y[1]<0)  k=1;                     	     //撞墙
  for(i=2;i<current_length;i++)
  {
	  if((x[1]==x[i])&(y[1]==y[i]))  k=1;             //撞自己
	}		
  return k;
}
/*****************
上下左右键位处理
*****************/
void key_scan()
{	  		  
		if(~(left&right&up&down))
		{
		 
			if(~down){addy=0;if(addx!=1)addx=-1; else addx=1;}
			if(~up){addy=0;if(addx!=-1)addx=1; else addx=-1;}
			if(~right){addx=0;if(addy!=-1)addy=1; else addy=-1;}
			if(~left){addx=0;if(addy!=1)addy=-1; else addy=1;}		 
		}	
}
/*****************
转换程序
*****************/
uchar transform(uchar temp) 
{
if(temp==15)return 0x80;
if(temp==14)return 0x40;
if(temp==13)return 0x20;
if(temp==12)return 0x10;
if(temp==11)return 0x08;
if(temp==10)return 0x04;
if(temp==9)return 0x02;
if(temp==8)return 0x01;

if(temp==7)return 0x80;
if(temp==6)return 0x40;
if(temp==5)return 0x20;
if(temp==4)return 0x10;
if(temp==3)return 0x08;
if(temp==2)return 0x04;
if(temp==1)return 0x02;
if(temp==0)return 0x01;
return 0;
}
/*****************
    显示程序
*****************/
void display(uchar speed)
{
	while(speed--)
 {
	for(i=0;i<MAX_length+1;i++)
   {
		 hang_l=0x00;hang_h=0x00;
		 lie=y[i];
		 if(x[i]<8)
		 {	 
	     hang_l=transform(x[i]);
			 hang_h=0x00;
		 }
		 if(x[i]>=8)
		 {
			 hang_l=0x00;
		   hang_h=transform(x[i]); 
     }			 		 
    key_scan();                                 //上下左右键位处理
    delay(1);                                   //显示延迟
   // hang_l=0x00;hang_h=0x00;
   }
 }
} 
void cartoon_1()
{
	int move=0;
  /***********预先显示动画***********/
	 while(1)
  {
		
	  for(j=0;j<5;j++)//modefied
	  {
	   for(i=0;i<=15;i++)
	   {
	    lie=i;hang_l=hangl_code[i+move];hang_h=hangh_code[i+move];
			delay(1);
			hang_l=0x00;hang_h=0x00;
	   }
    }
		move++;
		if(move==40)//image display
		{
			 for(jj=0;jj<4;jj++)
			{
				move=58;
       	for(j=0;j<10;j++){			
				for(i=0;i<=15;i++)
				{
					lie=i;hang_l=hangl_code[move+i];hang_h=hangh_code[move+i];
					delay(1);
					hang_l=0x00;hang_h=0x00;
				}}
				move=58+16;	
        for(j=0;j<10;j++){				
				for(i=0;i<=15;i++)
				{
					lie=i;hang_l=hangl_code[move+i];hang_h=hangh_code[move+i];
					delay(1);
					hang_l=0x00;hang_h=0x00;
				}}
			}
			break;
		}
		
  } 
	 /***********预先显示动画***********/
}
void cartoon_2()
{
	 int move=0;
  /******** game over ***********/
			 move=90;
			  while(1)
      {
			 
			for(j=0;j<4;j++)
			 {
				for(i=0;i<=15;i++)
				{
					lie=i;hang_l=hangl_code[i+move];hang_h=hangh_code[i+move];
					delay(1);
					hang_l=0x00;hang_h=0x00;
				}
			 }
		  move++;
		  if(move==120) break;
			}	
      /*********** game over ************/	
}
void display_music()
{
   /****************music******/
	TMOD=0x01;  EA=1; ET0=1;i=0;
	for(j=0;j<33;j++){
        music_m=music[i][0];music_n=music[i][1]; 
           if(music_m==0x00)
             {TR0=0;music_delay(music_n);i++;} 
           else if(music_m==0xFF)
             {TR0=0;music_delay(30);i=0;} 
           else if(music_m==music[i+1][0]) 
             {TR0=1;music_delay(music_n);TR0=0;music_pause();i++;}
           else
             {TR0=1;music_delay(music_n);i++;}
					 }
	 EA=0;ET0=0;beepIO=1;   
	/****************music******/
}
void di()
{
   beepIO=0;
   delay(50);
   beepIO=1;
}
void music_T0_int() interrupt 1
{
 beepIO=!beepIO;
 TH0=T[music_m][0]; TL0=T[music_m][1];
}

